﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using CellarDoor.Gui.Elements;
using CellarDoor.Gui.Animation;

namespace CellarDoor.Gui.Demo.Xbox
{
    public class DashboardPreview : UiPanel
    {
        private int index = 0;
        private const int WIDTH = 340;
        private const int HEIGHT = 260;
        private const int SPACE = 2;

        public int SelectedIndex
        {
            get { return index; }
        }

        public UiElement SelectedItem
        {
            get 
            {
                if (index >= 0 && index < Elements.Count)
                {
                    return Elements[index]; 
                }
                return null;
            }
        }

        public DashboardPreview(UiElement parent)
            : base(parent)
        {
            Initialize();
        }

        private void Initialize()
        {
            this.Height = 300;
            this.ElementName = null; // no visual style for the parent element
        }

        public UiPanel AddItem()
        {
            int index = Elements.Count;
            var panel = new UiPanel(this);
            
            panel.Width = WIDTH;
            panel.Height = HEIGHT;
            panel.Top = 0;
            panel.Left = index * (panel.Width + SPACE);
            panel.ElementName = "BackgroundWhite";
            panel.TextColor = Vector3.Zero;

            StartShift();

            return panel;
        }

        public void ShiftNext()
        {
            index++;
            if (index >= Elements.Count)
            {
                index = Elements.Count - 1;
                ShiftError();
            }
            else
            {
                StartShift();
            }
        }

        public void ShiftPrev()
        {
            index--;
            if (index < 0)
            {
                index = 0;
                ShiftError();
            }
            else
            {
                StartShift();
            }
        }

        public void Hit()
        {
            StartHit();
        }

        public void Return()
        {
            StartShift();
        }

        private void ShiftError()
        {
            for (int i = 0; i < Elements.Count; i++)
            {
                int delta = i - index;
                var panel = Elements[i];
                int direction = index == 0 ? 1 : -1;
                float y = -((HEIGHT * 1.15f) - HEIGHT) * 0.5f;
                if (i != index)
                {
                    y = 0;
                }
                var ani = new AnimatePosition(panel);
                panel.Controllers.Add(ani);
                ani.StartPosition = panel.Location;
                ani.EndPosition = new Vector2(delta * (WIDTH + SPACE) + WIDTH / 4 * direction, y);
                ani.Duration = 100;
                ani.EaseFunction = EaseFunction.InCubic;

                ani.StopAnimation += (e) =>
                {
                    e.Target.Controllers.Remove(e);
                    var back = new AnimatePosition(panel);
                    panel.Controllers.Add(back);
                    back.StartPosition = new Vector2(delta * (WIDTH + SPACE) + WIDTH / 4 * direction, y);
                    back.EndPosition = new Vector2(delta * (WIDTH + SPACE), y);
                    back.Duration = 100;
                    back.EaseFunction = EaseFunction.OutCubic;
                    back.StopAnimation += (ee) =>
                    {
                        ee.Target.Controllers.Remove(ee);
                    };
                    back.Start();
                };

                ani.Start();
            }
        }

        private void StartShift()
        {
            for (int i = 0; i < Elements.Count; i++)
            {
                int delta = i - index;
                var panel = Elements[i];
                // bring to front
                //var parent = panel.Parent;
                //panel.Detach();
                //parent.AddElement(panel);

                if (delta == 0)
                {
                    float y = -((HEIGHT * 1.15f) - HEIGHT) * 0.5f;
                    float x = delta * (WIDTH + SPACE) - SPACE * 1.15f;
                    panel.SlideTo(new Vector2(x, y), 250);
                    panel.InflateTo(new Vector2(WIDTH, HEIGHT) * 1.15f, 250);
                    panel.FadeIn(250);
                }
                else
                {
                    panel.SlideTo(new Vector2(delta * (WIDTH + SPACE), 0), 250);
                    panel.InflateTo(new Vector2(WIDTH, HEIGHT) * 1.0f, 250);
                    panel.FadeIn(250);
                }
            }
        }

        private void StartHit()
        {
            for (int i = 0; i < Elements.Count; i++)
            {
                int delta = i - index;
                var panel = Elements[i];

                if (delta == 0)
                {
                    float y = -((HEIGHT * 2f) - HEIGHT) * 0.5f;
                    float x = delta * (WIDTH + SPACE) - SPACE * 2f;
                    panel.SlideTo(new Vector2(x, y), 250);
                    panel.InflateTo(new Vector2(WIDTH, HEIGHT) * 2f, 250);
                    panel.FadeOut(500);
                }
                else
                {
                    panel.SlideTo(new Vector2(0, 0), 250);
                    panel.InflateTo(new Vector2(WIDTH, HEIGHT) * 1.0f, 250);
                    panel.FadeOut(150);
                }
            }
        }
    }
}
